/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.bo;

import org.ipti.br.tag.bean.dataManipulation.Month;
import org.ipti.br.tag.dao.ActorFacade;
import org.ipti.br.tag.dao.ActorScheduleFacade;
import org.ipti.br.tag.dao.UnityScheduleFacade;
import org.ipti.br.tag.entity.Discipline;
import org.ipti.br.tag.entity.Period;
import org.ipti.br.tag.entity.Unity;
import org.ipti.br.tag.entity.UnitySchedule;
import org.ipti.br.tag.entity.enums.WeekDay;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.ejb.Stateless;
import javax.inject.Inject;

/**
 *
 * @author root
 */
@Stateless
public class UnityScheduleBO implements Serializable {

    @Inject
    private UnityScheduleFacade unityScheduleDAO;
    
    @Inject
    private UnityBO unityBO;
    
    @Inject
    private ActorFacade actorFacade;
    
    @Inject
    private ActorScheduleFacade actorScheduleFacade;

    public UnityScheduleFacade getUnityScheduleDAO() {
        return unityScheduleDAO;
    }

    public void create(UnitySchedule unitySchedule) {
        getUnityScheduleDAO().create(unitySchedule);
    }

    public void edit(UnitySchedule unitySchedule) {
        getUnityScheduleDAO().edit(unitySchedule);
    }

    public void remove(UnitySchedule unitySchedule) {
        getUnityScheduleDAO().remove(unitySchedule);
    }

    public UnitySchedule find(Object id) {
        return getUnityScheduleDAO().find(id);
    }
    
    public UnitySchedule findBy(Unity unity, Discipline discipline, Calendar day, int index){
        if (discipline == null) {
            return getUnityScheduleDAO().find(unity, WeekDay.getDay(day.get(Calendar.DAY_OF_WEEK))).get(index);
        } else {
            return getUnityScheduleDAO().find(unity, WeekDay.getDay(day.get(Calendar.DAY_OF_WEEK)), discipline).get(index);
        }
    }

    public List<UnitySchedule> findAll() {
        return getUnityScheduleDAO().findAll();
    }
    
    public List<UnitySchedule> unityScheduleGivenUnityWeekday(Long unityID, WeekDay weekday) {
        return getUnityScheduleDAO().unityScheduleGivenUnityWeekday(unityID, weekday);
    }
    
    public List<WeekDay> unityScheduleWeekdaysGivenUnity(Unity unity,Discipline discipline) {
        return getUnityScheduleDAO().listWeekdays(unity, discipline);
    }

    public List<UnitySchedule> modifiedPerfFreqBetweenDate(Calendar initialDate, Calendar finalDate, Long serialNumber) {
        return getUnityScheduleDAO().modifiedPerfFreqBetweenDate(initialDate, finalDate, serialNumber);
    }
    
    public List<UnitySchedule> listForWeekDays(Unity unity, Discipline discipline){
        return getUnityScheduleDAO().listForWeekdays(unity, discipline);
    }
    
    public List<Date> loadDays(Unity unity, Discipline discipline, Month month, int year) {
        ArrayList<Date> dayList = new ArrayList<Date>();
        List<WeekDay> wDays = getUnityScheduleDAO().listWeekdays(unity, discipline);
        
        if (month != null && !wDays.isEmpty()) {
            Calendar cal = Calendar.getInstance();
            cal.set(year, month.ordinal(), 1);
            for(WeekDay day : wDays) {
                cal.set(Calendar.DAY_OF_WEEK,day.getCalendarDay());
                for(int i = 1;i<=cal.getActualMaximum(Calendar.DAY_OF_WEEK_IN_MONTH);i++) {
                    cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,i);
                    dayList.add(cal.getTime());
                }
            }
            Collections.sort(dayList);
            ListIterator<Date> it = dayList.listIterator();
            while(it.hasNext() && it.next().before(unity.getActivated().getTime())){
                it.remove();
            }
            if(unity.getDeactivated() != null){
                it = dayList.listIterator(dayList.size());
                while(it.hasPrevious() && it.previous().after(unity.getDeactivated().getTime())){
                    it.remove();
                }
            }
        }
        return dayList;
    }
    
    public Map<WeekDay, List<UnitySchedule> > map(Unity unity, Discipline discipline){
        EnumMap<WeekDay, List<UnitySchedule> > weekMap = new EnumMap<WeekDay, List<UnitySchedule>>(WeekDay.class);
        for (UnitySchedule us : getUnityScheduleDAO().listForWeekdays(unity, discipline)) {
            switch(us.getWeekDay()){
                case SUNDAY:
                    if(weekMap.containsKey(WeekDay.SUNDAY)){
                        weekMap.get(WeekDay.SUNDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.SUNDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.SUNDAY).add(us);
                    }
                    break;
                case MONDAY:
                    if(weekMap.containsKey(WeekDay.MONDAY)){
                        weekMap.get(WeekDay.MONDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.MONDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.MONDAY).add(us);
                    }
                    break;
                case TUESDAY:
                    if(weekMap.containsKey(WeekDay.TUESDAY)){
                        weekMap.get(WeekDay.TUESDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.TUESDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.TUESDAY).add(us);
                    }
                    break;
                case WEDNESDAY:
                    if(weekMap.containsKey(WeekDay.WEDNESDAY)){
                        weekMap.get(WeekDay.WEDNESDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.WEDNESDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.WEDNESDAY).add(us);
                    }
                    break;
                case THURSDAY:
                    if(weekMap.containsKey(WeekDay.THURSDAY)){
                        weekMap.get(WeekDay.THURSDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.THURSDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.THURSDAY).add(us);
                    }
                    break;
                case FRIDAY:
                    if(weekMap.containsKey(WeekDay.FRIDAY)){
                        weekMap.get(WeekDay.FRIDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.FRIDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.FRIDAY).add(us);
                    }
                    break;
                case SATURDAY:
                    if(weekMap.containsKey(WeekDay.SATURDAY)){
                        weekMap.get(WeekDay.SATURDAY).add(us);
                    } else {
                        weekMap.put(WeekDay.SATURDAY, new ArrayList<UnitySchedule>());
                        weekMap.get(WeekDay.SATURDAY).add(us);
                    }
                    break;
            }
        }
        return weekMap;
    }
    
    public int getInicialHour(Unity unity){
        int firstHour = 0;
        Period period = unity.getPeriod();
        if (period != null) {
            if (period.getDescription().equals("Matutino") || period.getDescription().equals("Integral")) {
                firstHour = 7;
            } else if (period.getDescription().equals("Vespertino")) {
                firstHour = 12;
            } else if (period.getDescription().equals("Noturno")) {
                firstHour = 18;
            }
        }
        return firstHour;
    }
}
